/**
 * Copyright (C) 2013- Iordan Iordanov
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */


package com.undatech.opaque;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.DrawableContainer;

public class CanvasDrawableContainer extends DrawableContainer {
	static final int CAPACITY_FACTOR = 7;
	
	// Soft cursor related variables
	private RectF cursorRect;
	private int hotX, hotY;
	private Bitmap softCursor;
	private boolean softCursorInit = false;
	
	// Bitmap related variables
	protected Bitmap bitmap;
	private Bitmap.Config cfg = Bitmap.Config.ARGB_8888;
	private int bitmapW;
	private int bitmapH;
	public Paint paint;
	
	CanvasDrawableContainer(int width, int height) {
		bitmapW = width;
		bitmapH = height;
		
		// To please createBitmap, we ensure the size it at least 1x1.
		if (bitmapW == 0) bitmapW = 1;
		if (bitmapH == 0) bitmapH = 1;
		
		bitmap = Bitmap.createBitmap(bitmapW, bitmapH, cfg);
		bitmap.setHasAlpha(false);
		
		cursorRect = new RectF();
		// Try to free up some memory.
		System.gc();
		softCursor = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
		
		paint = new Paint();
		paint.setFilterBitmap(true);
	}
	
	@Override
	public void draw(Canvas canvas) {
		try {
			synchronized (this) {
				canvas.drawBitmap(bitmap, 0.f, 0.f, paint);
				canvas.drawBitmap(softCursor, cursorRect.left, cursorRect.top, paint);
			}
		} catch (Throwable e) { }
	}

	void setCursorRect(int x, int y, float w, float h, int hX, int hY) {
		hotX = hX;
		hotY = hY;
		cursorRect.left   = x - hotX;
		cursorRect.right  = cursorRect.left + w;
		cursorRect.top    = y - hotY;
		cursorRect.bottom = cursorRect.top + h;
	}
	
	void moveCursorRect(int x, int y) {
		setCursorRect(x, y, cursorRect.width(), cursorRect.height(), hotX, hotY);
	}

	void setSoftCursor (int[] newSoftCursorPixels) {
		Bitmap oldSoftCursor = softCursor;
		softCursor = Bitmap.createBitmap(newSoftCursorPixels, (int)cursorRect.width(),
                                         (int)cursorRect.height(), Bitmap.Config.ARGB_8888);
		oldSoftCursor.recycle();
		softCursorInit = true;
	}
	
	RectF getCursorRect () {
		return cursorRect;
	}

	boolean isNotInitSoftCursor() {
		return softCursorInit;
	}

	/**
	 * 
	 * @return The smallest scale supported by the implementation; the scale at which
	 * the bitmap would be smaller than the screen
	 */
	float getMinimumScale(int canvaswidth, int canvasheight) {
		return Math.min((float)canvaswidth/bitmapW, (float)canvasheight/bitmapH);
	}	
	
	public void destroy() {
		if (bitmap != null)
			bitmap.recycle();
		bitmap      = null;	
		if (softCursor != null)
			softCursor.recycle();
		softCursor = null;
		cursorRect = null;
	}
	
	public void frameBufferSizeChanged (int width, int height) {
		android.util.Log.i("CanvasDrawableContainer", "bitmapsize changed = ("+bitmapW+","+bitmapH+")");
		if ( bitmapW < width || bitmapH < width ) {
			destroy();
			// Try to free up some memory.
			System.gc();
			bitmapW = width;
			bitmapH = height;
			bitmap = Bitmap.createBitmap(bitmapW, bitmapH, cfg);
			bitmap.setHasAlpha(false);
		}
	}
	
	@Override
	public int getIntrinsicHeight() {
		return bitmapH;
	}

	@Override
	public int getIntrinsicWidth() {
		return bitmapW;
	}

	@Override
	public int getOpacity() {
		return PixelFormat.OPAQUE;
	}

	@Override
	public boolean isStateful() {
		return false;
	}
}
